/*
Copyright (c) 2016 Ryan L. Guy

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgement in the product documentation would be
   appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../fluidsimulation.h"

void example_diffuse_inflow() {

    // This example will initialize an inflow fluid source and a
    // solid pillar obstacle. Foam/bubble/spray particles will be
    // generated by enabling the diffuse particle simulation feature
    //
    // Diffuse particles are output as a vertex only .PLY meshes
    // with the "diffuse" prefix followed by the frame number.
    //
    // ex: diffuse000000.ply, diffuse000001.ply, diffuse000002.ply

    int isize = 256;
    int jsize = 128;
    int ksize = 128;
    double dx = 0.0625;
    FluidSimulation fluidsim(isize, jsize, ksize, dx);

    // This option enables the diffuse particle simulation
    fluidsim.enableDiffuseMaterialOutput();

    // Maximum lifetime of a diffuse particle in seconds.
    // This value controls how quickly/slowly diffuse particles
    // fade from the simulation.
    fluidsim.setMaxDiffuseParticleLifetime(3.0);

    // Diffuse particles are generated in areas where the fluid
    // is likely to be aerated such as at wavecrests and areas of high
    // turbulence. This function call sets the wavecrest emission rate
    // and turbulence emission rate to the same values.
    //
    // To set different separate rates, use 
    //      setDiffuseParticleWavecrestEmissionRate(double) 
    //      setDiffuseParticleTurbulenceEmissionRate(double)
    fluidsim.setDiffuseParticleEmissionRates(37.0);

    // Limit the maximum number of particles simulated by the diffuse
    // particle simulator. 
    fluidsim.setMaxNumDiffuseParticles(6e6);

    double width, height, depth;
    fluidsim.getSimulationDimensions(&width, &height, &depth);

    // Initialize inflow fluid source located at one end of the
    // of the simulation domain.
    AABB inflowAABB(vmath::vec3(), 5*dx, 25*dx, 40*dx);
    vmath::vec3 inflowVelocity = vmath::vec3(10.0, 0.0, 0.0);
    CuboidFluidSource inflow(inflowAABB, inflowVelocity);
    inflow.setCenter(vmath::vec3(5*dx, 0.5*height, 0.5*depth));
    fluidsim.addCuboidFluidSource(&inflow);

    // Create a pillar of solid cells in the center of the domain
    std::vector<GridIndex> solidCells;
    vmath::vec3 center(0.5*width, 0.5*height, 0.5*depth);
    double pillarRadius = 15*dx;
    double rsq = pillarRadius * pillarRadius;
    for (int k = 0; k < ksize; k++) {
        for (int j = 0; j < jsize; j++) {
            for (int i = 0; i < isize; i++) {
                vmath::vec3 gpos = Grid3d::GridIndexToCellCenter(i, j, k, dx);
                vmath::vec3 v = gpos - center;
                double distsq = v.x*v.x + v.z*v.z;

                if (distsq < rsq) {
                    solidCells.push_back(GridIndex(i, j, k));
                }
            }
        }
    }
    fluidsim.addSolidCells(solidCells);

    fluidsim.addBodyForce(0.0, -25.0, 0.0);
    fluidsim.initialize();

    double timestep = 1.0 / 30.0;
    for (;;) {
        fluidsim.update(timestep);
    }
    
}